package pers.crayon.baseprogram;

import cn.hutool.core.net.NetUtil;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ConfigurableApplicationContext;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;

/**
 * 暂时禁用数据库连接
 *
 * @ServletComponentScan//防止 @WebListener 无效
 */
@Slf4j
@ServletComponentScan
@MapperScan("pers.crayon.baseprogram.mapper")
@SpringBootApplication
public class BaseProgramApplication {

    public static void main(String[] args) {
        makeApplicationPort();
        SpringApplication.run(BaseProgramApplication.class, args);

    }


    private static void checkBean(ConfigurableApplicationContext run) {
        // 检查分页插件配置
        Object mybatisPlusInterceptor = run.getBean("mybatisPlusInterceptor");
        if (null == mybatisPlusInterceptor) {
            log.info("=========分页插件配置失败=========");
        }
        // 查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        log.info("=============================容器中组件=============================");
        Arrays.stream(names).forEach(name -> log.info("组件:{}", name));
        log.info("=============================组件打印完毕=============================");
    }

    /**
     * 使程序端口有效
     */
    private static void makeApplicationPort() {
        // 获取配置文件端口
        int port = 8080;
        // 检查端口
        boolean usableLocalPort = NetUtil.isUsableLocalPort(port);
        if (!usableLocalPort) {
            log.info("端口不可以用，开始清理原端口占用线程");
            killTask(getProgramName(getPID(String.valueOf(port))));
        }
    }

    /**
     * 获取端口占用线程pid
     *
     * @param port
     * @return
     */
    private static String getPID(String port) {
        String pid = null;
        String[] args = new String[]{"cmd.exe", "/c", "netstat -aon|findstr", port};
        try (
                InputStream is = Runtime.getRuntime().exec(args).getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
        ) {
            String temp = br.readLine();
            if (null != temp) {
                String[] str = temp.split("\\s");
                pid = str[str.length - 1];
            }
        } catch (IOException e) {
            log.error("获取端口占用线程pid失败：{}", e.getMessage());
        }
        return pid;
    }

    /**
     * 获取programName 映像名称
     *
     * @param pid
     * @return
     */
    private static String getProgramName(String pid) {
        String programName = null;
        String[] args = new String[]{"cmd.exe", "/c", "tasklist|findstr", pid};
        try (
                InputStream is = Runtime.getRuntime().exec(args).getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
        ) {
            String temp = br.readLine();
            if (null != temp) {
                String[] str = temp.split("\\s");
                programName = str[0];
            }
        } catch (IOException e) {
            log.error("获取端口占用映像名称失败：{}", e.getMessage());
        }
        return programName;
    }

    /**
     * 杀死进程
     *
     * @param programName
     */
    private static void killTask(String programName) {
        String[] args = new String[]{"Taskkill", "/f", "/IM", programName};
        try {
            Runtime.getRuntime().exec(args);
        } catch (IOException e) {
            log.error("杀死进程失败：{}", e.getMessage());
        }
    }
}
